//Mike
#include "Util.h"
//#include "StarMap.h"
#include "App.h"
#include "Engine.h"
#include "Listener.h"
//#include "Sprite.h"




App*		gApp;
Model*		loadVertTexIndex(float*	verts,int nverts,float*	tex,int*	index,int nindex,const char*	saveName=0);

int	audioShutdown();



int	audioInit();


int		engineMouseX=0;
int		engineMouseY=0;


vec3	engineGetPickRay(int	x,int	y){
	GLfloat modelview[16];
	GLfloat projection[16];
	int		vp[4]={0,0,gApp->width,gApp->height};
	for(int t=0;t<16;t++){
		projection[t] = gApp->camProjection[t];
		modelview[t] = gApp->camModelView[t];
	}
	glGetFloatv(GL_MODELVIEW_MATRIX, modelview);
	glGetFloatv(GL_PROJECTION_MATRIX, projection);

	// obtain the Z position (not world coordinates but in range 0 - 1)
	GLfloat z_cursor=1.0f;//(1.0f*gApp->camNear/gApp->camFar)*2.0f;
	GLfloat x_cursor=(float)x;//+4.0f;
	GLfloat y_cursor=(float)gApp->height-y;
	//glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &z_cursor);
	// obtain the world coordinates
	vec3 pickRay;
	gluUnProject(x_cursor, y_cursor, z_cursor, modelview, projection, vp,&pickRay.x,&pickRay.y,&pickRay.z);
	return pickRay;
}

void	engineDrawSelected(Renderer*	renderer){
	Listener::sendMessage("drawSelectedSprites",renderer);
}

void	engineMouseClicked(int	x,int	y){
	engineMouseX=x;
	engineMouseY=y;
//	engineGetPickRay(x,y);
}

class	Engine : public bEngine
{
public:
	virtual void	step(){
		Listener::sendMessage("updateSprites");
	}
	virtual void	shutdown(){
		audioShutdown();
		Listener::sendMessage("shutdown");
	}
	virtual void	render(){
		vec3	dx=gApp->screenX*0.1f;
		vec3	dy=gApp->screenY*0.1f;
	//	int	rc=gStarCount;
		//if(rc>10000)rc=10000;
		float time=gApp->getTime();
		float scl=sin((time*0.1f))+40.0f;
	
		Renderer *renderer=gApp->getRenderer();
		
		Listener::sendMessage("updateSpriteCam");
		Listener::sendMessage("renderStarModel",renderer);
		Listener::sendMessage("startRendering",renderer);
		Listener::sendMessage("renderSprites",renderer);
		Listener::sendMessage("finishRendering",renderer);
	}


	virtual	bool	boot(App*	app){
		gApp=app;
		Renderer *renderer=gApp->getRenderer();

		
		Listener::sendMessage("buildStarModel",renderer);
		Listener::sendMessage("buildSprites",renderer);

		audioInit();
		
	
		return true;

	}
	Engine(){
	}
	virtual ~Engine(){
	};
};


bEngine*	gEngine;

void	engineMain(App*	app){
	gEngine = new Engine();
}

class	EngineClassListener : public Listener
{
public:
	virtual bool	message(const char *msg=null,void*	params=null)
	{
		if(msg=="engineStep"){
			gEngine->step();
		}else if(msg=="engineRender"){
			gEngine->render();
		}else if(msg=="engineDrawSelected"){
			engineDrawSelected((Renderer*)params);
		}else if(msg=="engineDoPicking"){
			static bool lWasDown=false;
			static bool rWasDown=false;
			gEngine->leftClicked=gEngine->rightClicked=false;
			if(!gApp->lMouseButton && !gApp->rMouseButton){lWasDown=false;rWasDown=false;return true;}
			if(gApp->lMouseButton && !lWasDown){lWasDown=true; gEngine->leftClicked=true;}
			if(gApp->rMouseButton && !rWasDown){rWasDown=true; gEngine->rightClicked=true;}

				//for(float t=1.0f;t<5.0f;t+=1.0f)gApp->drawLight((camRay*t/2.0f)+cp,dx*1.1f,dy*1.1f,0.1f);//(-camPos)+
			Listener::sendMessage("doSpritePicking");
		}else if(msg=="engineBoot"){
			srand(666);
			engineMain((App*)params);
			gEngine->boot((App*)params);
			return true;
		}else if(msg=="engineShutdown"){
			gEngine->shutdown();
		}else if(msg=="unhandledMessage"){
			logstr(format("Unhandled message:%s\n",params));
		}
		return true;
	}
	EngineClassListener(){
		Listener::listen(this,"engineStep");
		Listener::listen(this,"engineBoot");
		Listener::listen(this,"engineRenderSolid");
		Listener::listen(this,"engineRender");
		Listener::listen(this,"engineShutdown");
		Listener::listen(this,"engineDoPicking");
		Listener::listen(this,"engineDrawSelected");
		Listener::listen(this,"unhandledMessage");//Listen for this, so that we dont go into an infinite loop in message() on unhandled messages.


	}	
	virtual ~EngineClassListener(){}
};

EngineClassListener gEngineClassListener;